﻿#light

// 12.12.08 Justin Bozonier

// Original discussion:
// http://groups.google.com/group/f-for-scientists-book-club/browse_thread/thread/6cb9b0efeb99ac04

let distance xs ys =
  Seq.map2 (-) xs ys
  |> Seq.fold (fun t x -> t + x * x) 0.0
  |> sqrt;;

let rec private nearest_atom reference_point sample_points
(closest_point:(int*seq<float>)) (distance_val:float) =
   match reference_point, sample_points, closest_point with
   | (_, ref_point), (test_id, test_point) :: test_rest, (fit_id, fit_point) when
       (distance ref_point test_point) <= distance_val -> 
       nearest_atom reference_point test_rest (test_id, test_point) (distance ref_point test_point)
   | (_, ref_point), (test_id, test_point) :: test_rest, (fit_id, fit_point) when
       distance ref_point test_point > distance_val -> nearest_atom reference_point test_rest closest_point distance_val
   | _, [], _ -> closest_point

/// Function determines the point in other_points closest to the reference point.
let nearest reference_point (sample_point :: other_points) =
   nearest_atom
       reference_point
       other_points
       sample_point
       (distance (snd reference_point) (snd sample_point))